package pl.edu.romanow.alg

import net.liftweb.actor.LiftActor
import pl.edu.romanow.model.Database
import scala.collection.JavaConversions._
import com.tinkerpop.blueprints.pgm.oupls.jung.GraphJung
import pl.edu.romanow.model.GraphHelper._
import com.tinkerpop.blueprints.pgm.{Edge, Vertex}
import edu.uci.ics.jung.algorithms.transformation.DirectionTransformer
import org.apache.commons.collections15.Factory
import edu.uci.ics.jung.graph._
import com.tinkerpop.blueprints.pgm.impls.tg.TinkerGraph
import net.liftweb.common.Loggable
import java.util.ArrayList
import com.tinkerpop.blueprints.pgm.util.GraphHelper
import edu.uci.ics.jung.algorithms.cluster.{EdgeBetweennessClusterer, VoltageClusterer, BicomponentClusterer}
import pl.edu.romanow.query.Query
import scala.util.Random

/**
 * Created with IntelliJ IDEA.
 * User: jar
 * Date: 26.05.12
 * Time: 15:09
 * To change this template use File | Settings | File Templates.
 */

object ClusteringActor extends LiftActor with Loggable {

  case class DoCluster(query: Query)

  val random = new Random

  def randomColor = Integer.toHexString(random.nextInt(0xffffff))

  def doCluster(query: Query) {
    this ! DoCluster(query)
  }

  protected def messageHandler = {

    case DoCluster(q) => {

      var oldTime = System.nanoTime();

      logger.info("prepare graph")

      val bluePrintsG = subGraph(q.edgesSet)

      val newGraph = new GraphJung(bluePrintsG) with UndirectedGraph[Vertex, Edge] {
        override def getIncidentVertices(edge: Edge) =
          if (edge != null)
            super.getIncidentVertices(edge)
          else
            new ArrayList[Vertex]()

      }
      logger.info("prepare graph finished in:" + ((System.nanoTime() - oldTime) / 1000))
      logger.info("Begin transform")

      oldTime = System.nanoTime()

      //      val alg = new BicomponentClusterer[Vertex, Edge]()
      val alg = new EdgeBetweennessClusterer[Vertex, Edge](newGraph.getEdgeCount / 20)



      val out = alg.transform(newGraph)

      logger.info("end transform in :" + ((System.nanoTime() - oldTime) / 1000))
      logger.info("marking the graph")
      oldTime = System.nanoTime()


      out.foreach {
        item =>
          val color = randomColor
          item.foreach(v => Database.appCon.db.getVertex(v.getId) \("cluster", color)
          )
          println("Mam cluster: " + color + " " + item.size())
      }

      logger.info("Marking the graph done in: " + ((System.nanoTime() - oldTime) / 1000))


    }


  }

}
